import DingRTC from "dingrtc";

export default class DingRTCWrapper {
  constructor() {
    this.client = null;
    this.localStream = null;
    this.remoteStreams = new Map();
    this.participants = 0;
    this.connectionStatus = "disconnected";
    this.appId = null;
    this.userId = null;
    this.channel = null;

    // 事件处理器
    this.eventHandlers = {
      "connection-state-change": [],
      "stream-added": [],
      "stream-subscribed": [],
      "stream-removed": [],
      error: [],
    };
  }

  /**
   * 初始化客户端
   * @param {string} appId - 阿里云DingRTC应用ID
   * @param {string} userId - 用户唯一标识
   * @param {string} channel - 频道名称
   * @param {string} token - 认证令牌（从服务器获取）
   * @returns {Promise<boolean>} - 初始化是否成功
   */
  async initialize(appId, userId, channel, token) {
    if (!appId || typeof appId !== "string") {
      throw new Error("无效的AppID: 必须是非空字符串");
    }

    if (!userId || typeof userId !== "string") {
      throw new Error("无效的UserID: 必须是非空字符串");
    }

    if (!channel || typeof channel !== "string") {
      throw new Error("无效的Channel: 必须是非空字符串");
    }

    if (!token || typeof token !== "string") {
      throw new Error("无效的Token: 必须是非空字符串");
    }
    try {
      // 保存配置信息
      this.appId = appId;
      this.userId = userId;
      this.channel = channel;

      // 创建客户端实例
      this.client = DingRTC.createClient({
        mode: "rtc",
        codec: "h264",
      });

      // 设置事件监听
      this.setupEventListeners();

      // 加入频道
      await this.client.join(this.appId, this.channel, this.userId, token);

      this.connectionStatus = "connected";
      return true;
    } catch (error) {
      console.error("DingRTC 初始化失败:", error);
      this.connectionStatus = "failed";
      this.emitError(error);
      throw error;
    }
  }

  /**
   * 设置事件监听器
   */
  setupEventListeners() {
    if (!this.client) return;

    // 连接状态变化
    this.client.on("connection-state-change", (state) => {
      const stateMap = {
        disconnected: "disconnected",
        connecting: "connecting",
        connected: "connected",
        reconnecting: "reconnecting",
        failed: "failed",
      };

      this.connectionStatus = stateMap[state] || "disconnected";
      this.emit("connection-state-change", this.connectionStatus);
    });

    // 流添加事件
    this.client.on("stream-added", (event) => {
      const stream = event.stream;
      if (!this.remoteStreams.has(stream.getId())) {
        this.remoteStreams.set(stream.getId(), stream);
        this.participants = this.remoteStreams.size;
        this.emit("stream-added", stream);
      }
    });

    // 流订阅成功
    this.client.on("stream-subscribed", (event) => {
      const stream = event.stream;
      this.emit("stream-subscribed", stream);
    });

    // 流移除事件
    this.client.on("stream-removed", (event) => {
      const stream = event.stream;
      if (this.remoteStreams.has(stream.getId())) {
        this.remoteStreams.delete(stream.getId());
        this.participants = this.remoteStreams.size;
        this.emit("stream-removed", stream);
      }
    });

    // 错误处理
    this.client.on("error", (error) => {
      console.error("DingRTC 客户端错误:", error);
      this.emitError(error);
    });
  }

  /**
   * 发布本地媒体流
   * @param {MediaStream} mediaStream - 要发布的媒体流
   * @param {Object} options - 流选项
   * @param {boolean} options.audio - 是否包含音频
   * @param {boolean} options.video - 是否包含视频
   * @param {boolean} options.screen - 是否为屏幕共享
   * @returns {Promise<void>}
   */
  async publish(
    mediaStream,
    options = { audio: true, video: false, screen: false }
  ) {
    if (!this.client) {
      throw new Error("客户端未初始化");
    }

    try {
      // 创建DingRTC流
      this.localStream = DingRTC.createStream({
        streamID: `${this.userId}_${Date.now()}`,
        mediaStream: mediaStream,
        audio: options.audio,
        video: options.video,
        screen: options.screen,
      });

      // 初始化流
      await this.localStream.init();

      // 发布流
      await this.client.publish(this.localStream);
    } catch (error) {
      console.error("发布流失败:", error);
      this.emitError(error);
      throw error;
    }
  }

  /**
   * 取消发布流
   * @returns {Promise<void>}
   */
  async unpublish() {
    if (!this.client || !this.localStream) return;

    try {
      await this.client.unpublish(this.localStream);
      this.localStream.close();
      this.localStream = null;
    } catch (error) {
      console.error("取消发布失败:", error);
      this.emitError(error);
    }
  }

  /**
   * 订阅远程流
   * @param {Object} stream - DingRTC流对象
   * @returns {Promise<void>}
   */
  async subscribe(stream) {
    if (!this.client) return;

    try {
      await this.client.subscribe(stream);
    } catch (error) {
      console.error("订阅流失败:", error);
      this.emitError(error);
    }
  }

  /**
   * 离开频道
   * @returns {Promise<void>}
   */
  async leave() {
    if (!this.client) return;

    try {
      // 取消发布本地流
      if (this.localStream) {
        await this.unpublish();
      }

      // 关闭所有远程流
      this.remoteStreams.forEach((stream) => {
        stream.close();
      });
      this.remoteStreams.clear();
      this.participants = 0;

      // 离开频道
      await this.client.leave();

      // 重置状态
      this.connectionStatus = "disconnected";
    } catch (error) {
      console.error("离开频道失败:", error);
      this.emitError(error);
    } finally {
      this.client = null;
    }
  }

  /**
   * 添加事件监听
   * @param {string} event - 事件名称
   * @param {Function} handler - 事件处理函数
   */
  on(event, handler) {
    if (this.eventHandlers[event]) {
      this.eventHandlers[event].push(handler);
    } else {
      console.warn(`未知事件类型: ${event}`);
    }
  }

  /**
   * 移除事件监听
   * @param {string} event - 事件名称
   * @param {Function} handler - 事件处理函数
   */
  off(event, handler) {
    if (this.eventHandlers[event]) {
      this.eventHandlers[event] = this.eventHandlers[event].filter(
        (h) => h !== handler
      );
    }
  }

  /**
   * 触发事件
   * @param {string} event - 事件名称
   * @param {...any} args - 事件参数
   */
  emit(event, ...args) {
    if (this.eventHandlers[event]) {
      this.eventHandlers[event].forEach((handler) => {
        try {
          handler(...args);
        } catch (error) {
          console.error(`事件处理函数错误 (${event}):`, error);
        }
      });
    }
  }

  /**
   * 触发错误事件
   * @param {Error} error - 错误对象
   */
  emitError(error) {
    this.emit("error", error);
  }

  /**
   * 获取当前连接状态
   * @returns {string} - 连接状态
   */
  getConnectionStatus() {
    return this.connectionStatus;
  }

  /**
   * 获取参与者数量
   * @returns {number} - 参与者数量
   */
  getParticipantCount() {
    return this.participants;
  }

  /**
   * 获取远程流列表
   * @returns {Map} - 远程流Map
   */
  getRemoteStreams() {
    return this.remoteStreams;
  }
}
